<?php

namespace app\common\service;

use think\facade\Log;

/*
 * 豆包AI文章生成
 * */

class DouBaoAiArticleQuestionService extends ApiService
{

    private $apiKey;
    private $endpointId;
    private $apiUrl;

    public function __construct()
    {
        $this->apiKey = env('DOUBAO.DOUBAO_1_5_PRO_32_API_KEY', '');
        $this->endpointId = env('DOUBAO.DOUBAO_1_5_PRO_32_ENDPOINT_ID', '');
        $this->apiUrl = 'https://ark.cn-beijing.volces.com/api/v3/chat/completions';
    }

    /**
     * 调用火山引擎单轮对话
     *
     * @param string $$articleContent 文章内容
     * @return array AI回复内容
     * @throws Exception
     */
    public function getArticleQuestionByContent(string $articleContent): array
    {
        $content = <<<EOT
            请根据下方文章内容，从以下七个维度生成5道英语选择题，并给出答案与中文解析，并如示例所示JSON结构呈现。
            一、词汇能力：包括对词汇含义的理解，比如根据上下文猜测单词含义、区分近义词和反义词、识别不同词性的词汇等。可以考查特定单词的含义，也可以考查词汇的灵活运用和理解。
            二、细节把握能力：主要考查学生对文章具体细节信息的记忆和提取。例如人物的活动细节、特定事物的特征、时间长度等。要求学生能够准确记住文章中的具体描述，以便回答相关问题。
            三、文意理解能力：涵盖对文章主旨大意、特定人物行为、事件发展顺序等方面的理解。学生需要理解文章的整体内容，把握人物的行为动机和故事的发展脉络。
            四、句子理解能力：涉及对句子的理解，包括判断句子正误、理解句子中的时间信息、进行句式转换等。考查学生对句子结构和含义的准确把握。
            五、推理判断能力：要求学生根据文章内容进行合理的推测和判断。比如推断现象的原因、判断人物行为的合理性、预测可能发生的事情等。
            六、情感态度感知能力：考查学生对文章中人物情感状态的理解和感知，分析人物在特定情境下的感受和态度。
            七、综合运用能力：通常通过让学生复述故事、代入角色进行思考和表达等方式，考查学生对文章内容的理解和语言综合运用能力。
            此外，还可以考查对特定人物出现场景的记忆、对特定段落主题的把握和归纳、对词汇的语境推断以及对文化常识和特定文化词汇的理解和推断，对文章整体情境的理解和对特定节日的判断等方面。
            JSON结构示例：
            {
                "questionName": "What is the importance of the Gaokao in China?",
                "answer": "A",
                "option": [
                    {
                        "value": "A",
                        "name": "It determines the students' career paths."
                    },
                    {
                        "value": "B",
                        "name": "It marks the end of students' high school life."
                    },
                    {
                        "value": "C",
                        "name": "It has no impact on students' future."
                    },
                    {
                        "value": "D",
                        "name": "It is just a traditional ceremony."
                    }
                ],
                "analysis": "根据文章最后一段 The results of the Gaokao will determine not only which universities these students will grace but also, to\"a large extent, the trajectory of their careers and lives.\" 可知，Gaokao考试的结果不仅决定了学生能进入哪些大学，还在很大程度上决定了他们未来的职业和人生轨迹。因此，选项A是正确的。"
            }
            
            JSON结构字段说明:
            questionName: 英文题干内容
            answer: 正确答案选项
            option: 题目选项数组，每个元素是一个对象，每个对象中包含 'value' 和 'name' 2个字段。value是题目选项(A,B,C,D)，name是题目选项内容
            analysis: 题目中文解析
            注意事项:
            1.题干内容不得出现中文。
            2.正确答案只能是A,B,C,D中的一个。
            3.正确答案选项需打乱随机。
            4.确保返回的结果是有效的JSON格式。
        EOT;
        // 2. 构建认证头
        $authToken = 'Bearer ' . $this->apiKey;

        // 3. 构造单轮对话消息
        $payload = [
            'model' => $this->endpointId,
            'messages' => [
                ['role' => 'system', 'content' => $content],
                ['role' => 'user', 'content' => $articleContent],
            ]
        ];

        // 4. 调用CURL服务
        $response = HttpService::postJson(
            $this->apiUrl,
            $payload,
            ['Authorization: ' . $authToken]
        );
        // 5. 解析响应
        $jsonData = json_decode($response, true);
        logSave($response, '豆包文章内容响应');
        if (isset($jsonData['status']) && $jsonData['status'] == false) {
            getResponseException('响应超时');
        }
        if (isset($jsonData['error'])) {
            getResponseException('单词文章生成失败');
        }
        $reasoning_content = $jsonData['choices'][0]['message']['content'];
        //结果可能带有以下字符需要去除一下
        $reasoning_content = ltrim($reasoning_content, '```json');
        $reasoning_content = rtrim($reasoning_content, '```');


        $reasoning_content = json_decode($reasoning_content, true);
        logSave($reasoning_content, '生成文章题目转换结果');
        return $reasoning_content;
    }

    /**
     * 调用火山引擎单轮对话
     *
     * @param string $$articleContent 文章内容
     * @return array AI回复内容
     * @throws Exception
     */
    public function getArticleSentenceByContent(string $articleContent): array
    {
        $content = <<<EOT
            最高列举这篇文章中的10个核心短语，并从以下这3个方面对10个核心短语逐一进行知识点梳理，并如示例所示JSON结构呈现。
            1.分析短语的构成方式，如动词+介词、形容词+介词等，帮助学习者理解短语的形成逻辑。
            2.对于常用短语，可以提供其多种含义和用法，并通过不同的例句进行说明。
            3.对比相似短语的区别，帮助学习者准确区分和使用不同的短语。
            JSON结构示例：
            [
                {
                    "phrase": {
                        "english": "be at risk of",
                        "translation": "有……的风险。"
                    },
                   "analysis": "“be + 介词短语”表示处于某种状态。",
                   "example": {
                        "english": "People living near the river are at risk of flooding.",
                        "translation": "住在河边的人有洪水的风险。"
                   },
                   "similar": "与“be in danger of”的区别：两者意思较为相近，“be in danger of”更强调面临具体的危险情况，“be at risk of”更强调有发生危险的可能性。"
                },
                {
                    "phrase": {
                       "english": "lead to",
                       "translation": "导致；通向。"
                    },
                    "analysis": "动词 + 介词 to”表示结果或方向",
                    "example": {
                        "english": "Smoking can lead to serious health problems.",
                        "translation": "吸烟会导致严重的健康问题。"
                    },
                    "similar": "与“result in”的区别：“lead to”更强调一个过程导致的结果，“result in”更强调结果本身。"
                }
            ]
            JSON结构字段说明:
            example: 短语内容
            phrase->english: 短语英文内容字符串
            phrase->translation: 短语译文内容字符串
            analysis: 分析内容字符串
            example: 例句内容
            example->english: 例句英文内容字符串
            example->translation: 例句译文内容字符串
            similar: 相似短语内容字符串
            注意事项:
            1.确保返回的结果是有效的JSON格式。
            2.确保整体返回时间控制在30秒内。
        EOT;
        // 2. 构建认证头
        $authToken = 'Bearer ' . $this->apiKey;

        // 3. 构造单轮对话消息
        $payload = [
            'model' => $this->endpointId,
            'messages' => [
                ['role' => 'system', 'content' => $content],
                ['role' => 'user', 'content' => $articleContent],
            ]
        ];

        // 4. 调用CURL服务
        $response = HttpService::postJson(
            $this->apiUrl,
            $payload,
            ['Authorization: ' . $authToken]
        );
        // 5. 解析响应
        $jsonData = json_decode($response, true);
        logSave($response, '豆包文章句子响应');
        if (isset($jsonData['status']) && $jsonData['status'] == false) {
            getResponseException('响应超时');
        }
        if (isset($jsonData['error'])) {
            getResponseException('单词文章句子失败');
        }
        $reasoning_content = $jsonData['choices'][0]['message']['content'];
        //结果可能带有以下字符需要去除一下
        $reasoning_content = ltrim($reasoning_content, '```json');
        $reasoning_content = rtrim($reasoning_content, '```');

        $reasoning_content = json_decode($reasoning_content, true);
        logSave($reasoning_content, '生成文章句子转换结果');
        return $reasoning_content;
    }

    /**
     * 调用火山引擎单轮对话
     *
     * @param string $$articleContent 文章内容
     * @return array AI回复内容
     * @throws Exception
     */
    public function getArticleWordByContent(string $articleContent): array
    {
        $content = <<<EOT
            最高列举10个这篇文章中的核心词汇，并给出相关词汇的音标，译文，派生词等内容，具体内容以JSON结构字段说明为准。
            最终结果需严格按照以下JSON格式输出。
            JSON结构示例：
                    [
                        {
                            "word": "Reward",
                            "soundmark": {
                                "english": "rɪ'wɜːd",
                                "american": "rɪ'wɝd"
                            },
                            "paraphrase": "n. 报酬；奖赏；回报；v. 奖赏；酬谢；报答",
                            "derivative": "rewarding adj. 有报酬的；值得做的；rewardful adj. 酬谢的；rewardless adj. 无报酬的；rewardingly adv. 值得地",
                            "collocation": "reward system（奖励制度），reward oneself（犒劳自己），in reward for（作为对…的奖赏）",
                            "examples": [
                                {
                                    "english": "She received a reward for her excellent work.",
                                    "translation": "她因出色的工作而获得了奖赏。"
                                },
                                {
                                    "english": "Volunteering can be a rewarding experience, both for the person giving and the person receiving help.",
                                    "translation": "志愿服务对给予帮助的人和接受帮助的人来说都是一次有意义的经历。"
                                }
                            ],
                            "syllableChars": [
                                "re",
                                "ward"
                            ]
                        }
                    ]
            JSON结构字段说明:
            word: 词汇
            soundmark->english: 英式音标内容字符串
            soundmark->american: 美式音标内容字符串
            paraphrase: 释义内容字符串
            derivative: 派生词内容字符串
            collocation: 常见固定搭配内容字符串
            examples: 例句内容数组
            examples->english: 例句英文内容字符串
            examples->translation: 例句译文内容字符串
            syllableChars: 单词按照音节发音进行拆分后的组成项数组"
            注意事项:
            1.JSON内容中单词不得重复。
            2.确保整体返回时间控制在30秒内。
            3.确保返回的结果是有效的JSON格式。
        EOT;
        // 2. 构建认证头
        $authToken = 'Bearer ' . $this->apiKey;

        // 3. 构造单轮对话消息
        $payload = [
            'model' => $this->endpointId,
            'messages' => [
                ['role' => 'system', 'content' => $content],
                ['role' => 'user', 'content' => $articleContent],
            ]
        ];

        // 4. 调用CURL服务
        $response = HttpService::postJson(
            $this->apiUrl,
            $payload,
            ['Authorization: ' . $authToken]
        );
        // 5. 解析响应
        $jsonData = json_decode($response, true);
        logSave($response, '豆包文章核心词响应');
        if (isset($jsonData['status']) && $jsonData['status'] == false) {
            getResponseException('响应超时');
        }
        if (isset($jsonData['error'])) {
            getResponseException('单词文章句子失败');
        }
        $reasoning_content = $jsonData['choices'][0]['message']['content'];
        //结果可能带有以下字符需要去除一下
        $reasoning_content = ltrim($reasoning_content, '```json');
        $reasoning_content = rtrim($reasoning_content, '```');

//        Log::info('reasoning_content:' . $reasoning_content);
        $reasoning_content = json_decode($reasoning_content, true);
        logSave($reasoning_content, '豆包文章核心词响应');
        return $reasoning_content;
    }

    /**
     * 调用火山引擎单轮对话
     *
     * @param string $$articleContent 文章内容
     * @return array AI回复内容
     * @throws Exception
     */
    public function getArticleParagraphByContent(string $articleContent): array
    {
        $content = <<<EOT
                结合新课标引用原文例句对这篇短文中的时态进行知识点梳理，并如示例所示JSON结构呈现。
                1.根据英语新课标要求，引用原文例句对这篇短文中英语时态知识点的梳理。
                2.对例句进行分析，如没有例句则不用返回对应时态且不要重复。

                JSON结构示例：
                [
                    {
                        "name": "一般过去时(Simple Past Tense) 描述过去发生的动作或状态。",
                        "examples": [
                            {
                                "sentence": "Summer had just begun, but the heat wave was already there.",
                                "analysis": "这句话使用了过去完成时“had just begun”来描述夏天的开始，同时使用了一般过去时“was”来描述热浪已经到来。这里通过不同的时态，清晰地表达了两个不同时间点的状况。"
                            }
                        ]
                    },
                    {
                        "name": "现在完成时(Present Perfect Tense) 描述过去发生的动作对现在造成的影响或结果。",
                        "examples": [
                            {
                                "sentence": "In high temperatures, when the body temperature goes up above 40°C, it will do harm to people’s health. This could happen in as quickly as 30 minutes.",
                                "analysis": "在这句话中，“could happen”使用了现在完成时，表示这种高温导致的健康危害可能在30分钟内发生，强调了过去的动作（温度上升）对现在（可能的健康影响）的潜在影响。"
                            }
                        ]
                    },
                    {
                        "name": "一般现在时(Simple Present Tense) 描述经常性、习惯性的动作或普遍真理。",
                        "examples": [
                            {
                                "sentence": "People with high blood pressure, people who work or exercise outside and people over the age of 65 are most in danger. But it can happen to anyone.",
                                "analysis": "这句话中使用了“are”和“can happen”两种时态。前半部分使用一般现在时来描述某些人群（高血压患者、户外工作者、老年人）更容易受到高温的影响，而后半部分使用一般现在时的否定形式“can happen”来强调高温危害的普遍性，即它可能发生在任何人身上。"
                            },
                            {
                                "sentence": "For children's safety, parents must carefully read the activity instructions.",
                                "analysis": "这句话强调了父母为了孩子的安全必须仔细阅读活动说明书的责任，这是一种普遍真理或经常性状态，因此使用了一般现在时。"
                            }
                        ]
                    },
                    {
                        "name": "现在进行时(Present Continuous Tense) 描述当前正在进行的动作。",
                        "examples": [
                            {
                                "sentence": "原文中没有直接出现现在进行时的例句，但可以根据语境补充。",
                                "analysis": "虽然原文没有直接使用现在进行时，但可以通过理解语境来补充。例如，“When the body temperature goes up above 40°C”可以理解为当前正在发生的动作，即体温超过40°C的情况。这种用法强调了高温对健康的即时影响。"
                            }
                        ]
                    },
                    {
                        "name": "一般将来时(Simple Future Tense) 描述将来某个时间点将要发生的动作或状态。",
                        "examples": [
                            {
                                "sentence": "原文中没有直接出现一般将来时的例句，但可以根据语境推测。",
                                "analysis": "虽然原文没有明确使用一般将来时，但可以通过语境来推测。例如，“When the body temperature goes up above 40°C, it will do harm to people’s health”这句话暗示了在未来某个时间点（体温超过40°C时），将会发生对健康有害的情况。这种用法用于强调未来可能发生的动作或状态。"
                           }
                        ]
                    }
                ]
                JSON结构字段说明:
                name: 时态类型名称
                examples: 原文例句数组
                examples->sentence: 例句英文内容字符串
                examples->analysis: 例句分析内容字符串
                注意事项:
                1.确保返回的结果是有效的JSON格式。
        EOT;
        // 2. 构建认证头
        $authToken = 'Bearer ' . $this->apiKey;

        // 3. 构造单轮对话消息
        $payload = [
            'model' => $this->endpointId,
            'messages' => [
                ['role' => 'system', 'content' => $content],
                ['role' => 'user', 'content' => $articleContent],
            ]
        ];

        // 4. 调用CURL服务
        $response = HttpService::postJson(
            $this->apiUrl,
            $payload,
            ['Authorization: ' . $authToken]
        );
        // 5. 解析响应
        $jsonData = json_decode($response, true);
        logSave($response, '豆包文章时态响应');
        if (isset($jsonData['status']) && $jsonData['status'] == false) {
            getResponseException('响应超时');
        }
        if (isset($jsonData['error'])) {
            getResponseException('单词文章句子失败');
        }
        $reasoning_content = $jsonData['choices'][0]['message']['content'];
        //结果可能带有以下字符需要去除一下
        $reasoning_content = ltrim($reasoning_content, '```json');
        $reasoning_content = rtrim($reasoning_content, '```');

//        Log::info('reasoning_content:' . $reasoning_content);
        $reasoning_content = json_decode($reasoning_content, true);
        logSave($reasoning_content, '豆包文章时态响应');
        return $reasoning_content;
    }

    /**
     * 调用火山引擎单轮对话
     *
     * @param string $$articleContent 文章内容
     * @return array AI回复内容
     * @throws Exception
     */
    public function getArticleSentenceStructureByContent(string $articleContent): array
    {
        $content = <<<EOT
                结合新课标引用原文例句对这篇短文中的句子结构从以下5个方面进行知识点的梳理，并如示例所示JSON结构呈现。
                1.简单句
                2.并列句
                3.复合句
                4.特殊句式
                5.固定句型

                JSON结构示例：
                [
                    {
                        "type": "简单句",
                        "children": [
                            {
                                "name": "主语 + 谓语 + 宾语",
                                "sentence": "Beijing had its hottest days in the third week of June.",
                                "analysis": "此句中，“Beijing”是主语，“had”是谓语，“its hottest days”是宾语。"
                            },
                            {
                                "name": "主语 + 系动词 + 表语",
                                "sentence": "The highest temperature was 41°C.",
                                "analysis": "在这个句子中，“The highest temperature”是主语，“was”是系动词，“41°C”是表语。"
                            }
                        ]
                    },
                    {
                        "type": "并列句",
                        "children": [
                            {
                                "name": "并列连词（如 and, but, or）连接两个简单句",
                                "sentence": "In high temperatures, when the body temperature goes up above 40°C, it will do harm to people’s health.",
                                "analysis": "此句由两个简单句构成，“in high temperatures”和“when the body temperature goes up above 40°C, it will do harm to people’s health”。它们由并列连词“when”连接。"
                            }
                        ]
                    },
                    {
                        "type": "复合句",
                        "children": [
                            {
                                "name": "主句 + 从句（由从属连词如 because, since, if, whether等引导）",
                                "sentence": "Because of that, there were many people in morgues and hospitals.",
                                "analysis": "在这个句子中，“there were many people in morgues and hospitals”是主句，而“Because of that”是从句，由从属连词“because of”引导。"
                            },
                            {
                                "name": "主句 + 宾语从句（由连接副词如 what, where, when等，或连接代词如 who, which, that等引导）",
                                "sentence": "",
                                "analysis": "此篇文章中没有出现宾语从句的例子"
                            }
                        ]
                    },
                    {
                        "type": "特殊句式",
                        "children": [
                            {
                                "name": "倒装句",
                                "sentence": "At least 96 people died.",
                                "analysis": "此句是一个倒装句，正常语序应为“96 people died at least”。在这里，“at least”作为状语被置于句首，形成了倒装。"
                            },
                            {
                                "name": "省略句",
                                "sentence": "",
                                "analysis": "此篇文章中没有出现明显的省略句例子"
                            }
                        ]
                    },
                    {
                        "type": "固定句型",
                        "children": [
                            {
                                "name": "so…that…（如此…以至于…）",
                                "sentence": "",
                               "analysis": "此篇文章中没有直接使用“so…that…”句型，但“it will do harm to people’s health”可以视为“so…that…”的一种隐含表达，即“伤害人们的健康是如此之大”。"
                            },
                            {
                                "name": "such…that…（如此…以至于…）",
                                "sentence": "",
                                "analysis": "此篇文章中没有直接使用“such…that…”句型。"
                            }
                        ]
                    }
                ]

                JSON结构字段说明:
                type: 句式类型名称
                children: 句子结构句型数组
                children->name: 句型内容字符串
                children->sentence: 原文例句内容字符串
                children->analysis: 例句分析内容字符串

                注意事项:
                1.如文中没有出现对应句式则不用返回。
                2.句子结构句型内容不得重复。
                3.如type字段的children值为空组则不用返回。
                4.确保整体返回时间控制在30秒内。
                5.确保返回的结果是有效的JSON格式。
        EOT;
        // 2. 构建认证头
        $authToken = 'Bearer ' . $this->apiKey;

        // 3. 构造单轮对话消息
        $payload = [
            'model' => $this->endpointId,
            'messages' => [
                ['role' => 'system', 'content' => $content],
                ['role' => 'user', 'content' => $articleContent],
            ]
        ];

        // 4. 调用CURL服务
        $response = HttpService::postJson(
            $this->apiUrl,
            $payload,
            ['Authorization: ' . $authToken]
        );
        // 5. 解析响应
        $jsonData = json_decode($response, true);
        logSave($response, '豆包文章句子结构响应');
        if (isset($jsonData['status']) && $jsonData['status'] == false) {
            getResponseException('响应超时');
        }
        if (isset($jsonData['error'])) {
            getResponseException('单词文章句子失败');
        }
        $reasoning_content = $jsonData['choices'][0]['message']['content'];
        //结果可能带有以下字符需要去除一下
        $reasoning_content = ltrim($reasoning_content, '```json');
        $reasoning_content = rtrim($reasoning_content, '```');

//        Log::info('reasoning_content:' . $reasoning_content);
        $reasoning_content = json_decode($reasoning_content, true);
        logSave($reasoning_content, '豆包文章句子结构响应');
        return $reasoning_content;
    }
}